package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.aip.AipFaceTemplate;
import com.itheima.autoconfig.huanxin.HuanXinTemplate;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.autoconfig.sms.SmsTemplate;
import com.itheima.domain.db.*;
import com.itheima.domain.vo.SettingVo;
import com.itheima.domain.vo.UserInfoVo;
import com.itheima.service.db.*;
import com.itheima.util.ConstantUtil;
import com.itheima.util.JwtUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Component  //加入到spring的容器
public class UserManager {

    @Reference
    private UserService userService;
    //保存用户方法
    public Long save(User user) {

        //1.加密处理
        //加密: 没有解密  md5不可解密
        String md5Pwd = SecureUtil.md5( user.getPassword() );
        user.setPassword( md5Pwd );

        //2.保存对象
        Long id = userService.save(user);

        return id;
    }

    //根据手机号查询用户
    public User findByPhone(String phone) {
        return userService.findByPhone(phone);
    }


    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    //短信发送
    public void sendSms(String phone) {
        //TODO 标注, 以后此处修改成真实发送短信的代码  目前写死验证码为123456
        //1.生成随机验证码
        //int code = RandomUtil.randomInt(6);
        //2.发送验证码
        //smsTemplate.sendSms(phone ,String.valueOf(code) );

        //3.保存到redis 验证码超时时间 5分钟
        stringRedisTemplate.opsForValue().set(ConstantUtil.SMS_CODE + phone , "123456" , Duration.ofMinutes(5));
    }

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Reference
    private DeblockingService deblockingService;
/*
    *//**
     * 登录或者注册
     * 1.对比验证码
     * 2.对比失败抛出异常
     * 3.对比成功 根据手机号查询用户对象
     * 4.如果查询不到 执行注册
     * 5.如果查询到用户 执行登录
     * 6.登录或者注册 后 将数据存入redis
     * 7.构建返回数据
     * @param phone
     * @param verificationCode
     *//*
    public Map regOrLogin(String phone, String verificationCode) {
        //从redis中获得验证码
        String code = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + phone);
        //1.对比验证码
        if(!StrUtil.equals(verificationCode , code)){
            //2.对比失败抛出异常
            throw  new RuntimeException("验证码输入错误");
        }

        //当验证码对比之后 redis中验证码可以删除了
        stringRedisTemplate.delete(ConstantUtil.SMS_CODE + phone);

        //创建log
        Log log = new Log();

        //3.对比成功 根据手机号查询用户对象
        User user = userService.findByPhone(phone);
        Boolean flag = false;
        //4.如果查询不到 执行注册
        if(user == null){
            //执行注册
            user = new User();
            user.setPhone(phone); //设置手机号
            user.setPassword( ConstantUtil.INIT_PASSWORD );//设置密码
            Long id = save(user);
            user.setId(id); //保存成功   赋值id的目的是 : 后续代码需要构建token使用
            System.out.println("注册后的用户对象:" + user);

            //huanXinTemplate.register(id); 环信只支持100个用户  TODO 以后开发以后把注释打开
            flag = true; //执行了注册标志

            log.setType("0102");
        }else{
            //5.如果查询到用户 执行登录
            flag = false;//执行了登录标志
            log.setType("0101");
        }

        log.setUserId(user.getId());//用户id
        log.setLogTime(DateUtil.today());//操作时间
        log.setPlace("北京"); //操作地点 暂时写死 需要前端提供 否则只能从mongo中查询
        log.setEquipment("小米");//登录设备    暂时写死 需要前端提供
        //log.setType();//操作类型

        rocketMQTemplate.convertAndSend("tanhua-log-161" , log);

        //6.登录或者注册 后 将数据存入redis
        //转换token
        Map<String ,Object> map = new HashMap<>();
        map.put("id" , user.getId());
        map.put("phone", user.getPhone());
        String token = JwtUtil.createToken(map);
        //存入token 主要是存入用户的登录状态 (所有的登陆信息 在token中)  此时的值 无所谓   , 设置过期的时间
        stringRedisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN + token , "1"  , Duration.ofDays(7));

        //7.构建返回数据  token 和 isNew
        Map returnMap = new HashMap();
        returnMap.put("token" , token );
        returnMap.put("isNew" , flag);
        return returnMap;

    }*/
    /**
     * 登录或者注册
     * 1.对比验证码
     * 2.对比失败抛出异常
     * 3.对比成功 根据手机号查询用户对象
     * 4.如果查询不到 执行注册
     * 5.如果查询到用户 执行登录
     * 6.登录或者注册 后 将数据存入redis
     * 7.构建返回数据
     * @param phone
     * @param verificationCode
     */

    public Map regOrLogin(String phone, String verificationCode) {
        //从redis获取用户输入的验证码
        String code = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + phone);

        //对比验证码
        if(!StrUtil.equals(verificationCode,code)){

            //如果验证码不正确 则抛出异常
            throw new RuntimeException("验证码输入有误");
        }
        //删除redis中的验证码
        stringRedisTemplate.delete(ConstantUtil.SMS_CODE +phone);

        //判断用户是否存在（是否为新用户）
        User user = userService.findByPhone(phone);

        Boolean flag = false;
        if (user==null){
            //创建新用户
            user = new User();
            //设置用户手机号
            user.setPhone(phone);
            //设置用户密码
            user.setPassword(ConstantUtil.INIT_PASSWORD);

            Long id = save(user);

            //注册用户
            user.setId(id);


            //环信只支持100个用户 超过100需要购买企业版
            huanXinTemplate.register(id);

            //执行了注册标志
            flag=true;
        }


        //查询解冻数据
        Deblocking deblocking = deblockingService.findByUserId(user.getId());
        //如果解冻数据不为空
        if(deblocking!=null){
            //删除redis的冻结数据
            stringRedisTemplate.delete(ConstantUtil.FREEZE_USER_LOGIN+user.getId());
        }
        //登录或者注册 后 将数据存入redis
        //转换token
        Map<String,Object> map=new HashMap<>();
        map.put("id",user.getId());
        map.put("phone", user.getPhone());
        String token = JwtUtil.createToken(map);

        stringRedisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN + token,"1",Duration.ofDays(7));



        //构建返回数据  token 和 isNew
        Map returnMap = new HashMap();
        returnMap.put("token" , token );
        returnMap.put("isNew" , flag);
        return returnMap;

    }

    @Reference
    private UserInfoService userInfoService;
    //保存用户基础信息的方法
    public Map saveUserInfo(UserInfo userInfo) {
        //暂时写死一些数据 因为前段没有传入
        userInfo.setTags("单身,本科,年龄相仿"); //这个是必须给的
        userInfo.setAge(18);
        userInfo.setProfession("计算机");
        userInfo.setIncome("30");
        userInfo.setMarriage(1);
        userInfo.setEducation("本科");
        //保存用户基础信息
        userInfoService.save(userInfo);


        return null;
    }

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private AipFaceTemplate aipFaceTemplate;
    /**
     * 保存用户对象
     */
    public Map updateUserInfo(MultipartFile headPhoto, Long id) throws IOException {

        //1.百度云人脸识别
        boolean flag = aipFaceTemplate.detect(headPhoto.getBytes());
        if(flag){
            //人脸的情况下
            //2.文件上传
            String uploadPath = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
            //3.正常保存到数据库即可
            UserInfo userInfo = new UserInfo();
            userInfo.setId( id ); //赋值id
            userInfo.setCoverPic("https://"+uploadPath); //朋友圈封面
            userInfo.setAvatar("https://"+uploadPath);//头像
            userInfoService.update(userInfo);//修改头像
        }

        return null;
    }

    //根据用户的id查询用户的信息
    public UserInfoVo findByUserId(Long userId) {
        //1.查询数据库的实体数据
        UserInfo userInfo = userInfoService.findById(userId);

        //2.创建前端所需要的vo对象
        UserInfoVo userInfoVo = new UserInfoVo();

        //3.数据转移  source 数据的来源 target 数据的去向
        BeanUtil.copyProperties(userInfo , userInfoVo); //99%的数据
        //特殊设置
        userInfoVo.setAge( userInfo.getAge().toString() );
        return userInfoVo;
    }

    //修改用户的个人信息
    public void updateUserInfo(UserInfo userInfo) {
        //修改用户的个人信息
        userInfoService.update(userInfo);
    }


    @Reference
    private QuestionService questionService;

    @Reference
    private NotificationService notificationService;
    //查询用户的通知信息
    public SettingVo findSettings() {
        //1.获得用户id
        Long id = UserHolder.getId();

        //2.查询用户的问题
        Question question = questionService.findByUid(id);
        //3.查询用户的通知
        Notification notification = notificationService.findByUserId(id);

        //4.封装vo
        SettingVo settingVo = new SettingVo();
        settingVo.setId(id);
        settingVo.setPhone( UserHolder.get().getPhone() );
        if(question == null){
            settingVo.setStrangerQuestion("你喜欢高山还是流水?"); //如果数据库没有 给一个默认问题
        }else{
            settingVo.setStrangerQuestion(question.getStrangerQuestion()); //如果数据库没有 给一个默认问题
        }
        if(notification == null ){ //没有设置任何通知
            settingVo.setGonggaoNotification(false);
            settingVo.setLikeNotification(false);
            settingVo.setPinglunNotification(false);
        }else{
            settingVo.setGonggaoNotification(notification.getGonggaoNotification());
            settingVo.setLikeNotification(notification.getLikeNotification());
            settingVo.setPinglunNotification(notification.getPinglunNotification());
        }
        //5.返回
        return settingVo;
    }
    public void sendSmss(Long id) {
        User user = userService.findById(id);
        sendSms(user.getPhone());
    }

    public Map checkVerificationCode(String code) {
        Long id = UserHolder.getId();
        User user = userService.findById(id);
        String phone = user.getPhone();
        System.out.println(code+"code");
        String code1 = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + phone);
        System.out.println(code1+"code1");
        Map map = new HashMap();
        System.out.println(111);
        boolean flag=false;
        if (StrUtil.equals(code1, code)) {

            System.out.println(2);
            stringRedisTemplate.delete(ConstantUtil.SMS_CODE + phone);
            map.put("verification", true);

        } else {
            map.put("verification", false);
            System.out.println(3);

        }
        return map;
    }


    public void updatePhone(String phone, Long id) {

        String examplePhone = "^1(?:3\\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\\d|9\\d)\\d{8}$";
        User user = userService.findByPhone(phone);
        User user1 = userService.findById(id);
        if (user!=user1 && (phone.matches(examplePhone))) {
            userService.updatePhone(id, phone);
        } else {
            throw new RuntimeException("手机号修改失败");
        }
    }


}
